/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package audio.player;

/**
 *
 * @author głodoś
 */
import java.io.ByteArrayInputStream;
import java.io.InputStream;


/**
 * An example of playing a sound with an echo filter.
 *
 * @see EchoFilter
 * @see SimpleSoundPlayer
 */
public class EchoFilter extends SoundFilter{

  public static void main(String[] args) {
//
//    // load the sound
//    SimpleAudioPlayer sound = new SimpleAudioPlayer("music.wav");
//
//    // create the sound stream
//    InputStream is = new ByteArrayInputStream(sound.getSamples());
//
//    // create an echo with a 11025-sample buffer
//    // (1/4 sec for 44100Hz sound) and a 60% decay
//    EchoFilter filter = new EchoFilter(11025, .6f);
//
//    // create the filtered sound stream
//    is = new FilteredAudioStream(is, filter);
//
//    // play the sound
//    sound.play(is);
//
//    // due to bug in Java Sound, explicitly exit the VM.
//    System.exit(0);
  }


  private short[] delayBuffer;

  private int delayBufferPos;

  private float decay;

  /**
   * Creates an EchoFilter with the specified number of delay samples and the
   * specified decay rate.
   * <p>
   * The number of delay samples specifies how long before the echo is
   * initially heard. For a 1 second echo with mono, 44100Hz sound, use 44100
   * delay samples.
   * <p>
   * The decay value is how much the echo has decayed from the source. A decay
   * value of .5 means the echo heard is half as loud as the source.
   */
  public EchoFilter(int numDelaySamples, float decay) {
    delayBuffer = new short[numDelaySamples];
    this.decay = decay;
  }

  public synchronized void setDelaySamples(int num){
      short[] newBuffer = new short[num];
      delayBuffer = null;
      //System.arraycopy(delayBuffer, 0, newBuffer, 0, Math.min(num, delayBuffer.length));
      delayBuffer = newBuffer;
      delayBufferPos = 0;
  }
  public synchronized void setDecay(float decay){
      this.decay = decay;
  }
  public int getDelaySamples(){
      return delayBuffer.length;
  }
  public float getDecay(){
      return decay;
  }
  /**
   * Gets the remaining size, in bytes, of samples that this filter can echo
   * after the sound is done playing. Ensures that the sound will have decayed
   * to below 1% of maximum volume (amplitude).
   */
  public synchronized int getRemainingSize() {
    float finalDecay = 0.01f;
    // derived from Math.pow(decay,x) <= finalDecay
    int numRemainingBuffers = (int) Math.ceil(Math.log(finalDecay)
        / Math.log(decay));
    int bufferSize = delayBuffer.length * 2;

    return bufferSize * numRemainingBuffers;
  }

  /**
   * Clears this EchoFilter's internal delay buffer.
   */
  public synchronized void reset() {
    for (int i = 0; i < delayBuffer.length; i++) {
      delayBuffer[i] = 0;
    }
    delayBufferPos = 0;
  }

  /**
   * Filters the sound samples to add an echo. The samples played are added to
   * the sound in the delay buffer multipied by the decay rate. The result is
   * then stored in the delay buffer, so multiple echoes are heard.
   */
  public synchronized void filter(byte[] samples, int offset, int length) {

    for (int i = offset; i < offset + length; i += 2) {
      // update the sample
      short oldSample = getSample(samples, i);
      short newSample = (short) (oldSample + decay * delayBuffer[delayBufferPos]);
      setSample(samples, i, newSample);

      // update the delay buffer
      delayBuffer[delayBufferPos] = newSample;
      delayBufferPos++;
      if (delayBufferPos == delayBuffer.length) {
        delayBufferPos = 0;
      }
    }
  }
}









